#include "Benchmark.h"
#include <time.h>

namespace Utilities {

INIT_FACTORY(Benchmark)

Benchmark::Benchmark( int _nbTests,
		BasePtr _base,
		Array<BenchmarkElement<TraitementSignal>> & _signalProcessing,
		Array<BenchmarkElement<Apprentissage>> & _classifiers,
		ResultFormatWriterPtr _out){
	base = _base;
	signalProcessing = _signalProcessing;
	classifiers = _classifiers;
	out = _out;
	nbTests = _nbTests;
}

vector<string> Benchmark::getParametersValues(BenchmarkBornes & bb){
		vector<string> params;
		for (int j=0; j<bb.size; j++){
			if ( bb.inf[j] != bb.sup[j] ) {
				double inf = ToDouble::parse(bb.inf[j]);
				double sup = ToDouble::parse(bb.sup[j]);
				double val = sup-((unsigned)((double)std::rand()/((double)RAND_MAX+1)*(sup-inf)));
				params.push_back(ToString::parse(val));
			} else params.push_back(bb.inf[j]);
		}
		return params;
}

void Benchmark::perform(){
	Array<TraitementSignalPtr> traitement;
	Array<ApprentissagePtr> classificateur;

	srand(time(NULL));
	for (int j=0; j<nbTests; j++){
		traitement.clear();
		for (int i=0; i<signalProcessing.size(); i++){
			vector<string> params = getParametersValues(signalProcessing[i].getBornes());
			traitement.add(TraitementSignal::getFactoryManager()->create(signalProcessing[i].getElement()->getType(), params));
			/// envoie des infos
			params.insert(params.begin(), signalProcessing[i].getElement()->getType());
			out->writeInfo(params);
		}

		classificateur.clear();
		for (int i=0; i<classifiers.size(); i++){
			vector<string> params = getParametersValues(classifiers[i].getBornes());
			classificateur.add(
				(Apprentissage *) Apprentissage::getFactoryManager()->create(classifiers[i].getElement()->getType(), params));
			/// envoie des infos
			params.insert(params.begin(), classifiers[i].getElement()->getType());
			out->writeInfo(params);
		}

		SimpleChaine chaine(base, traitement, classificateur, out);
		try {
			chaine.train();
			chaine.recognize();
		} catch (exception & ex){
			out->writeError(ex.what());
		}
	}
	out->flush();
}
}